home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
BCCAPP.ARJ
/
FIELD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-15
|
11KB
|
591 lines
/*
*
* Field editing system.
*
* (C) 1990 Vision Software
*
* $Id: field.c 1.102 91/05/04 17:19:08 pcalvin beta $
*
* Comments:
*
* This class provides EDIT with the individual field control. In the
* future, we may be used by other classes that require formated input..
*
* Bugs:
*
* Probably, none documented.
*
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdhdr.h>
#include <adl.h>
#include <menu.h>
#include <field.h>
#include "lowlevel.h"
/*
* Title/Information field contruction..
*/
IF::IF(WINDOW &rwndDest,ROW rowStart,COL colStart,SZ sz) : rwnd(rwndDest)
{
szMessage = sz;
row = rowStart;
col = colStart;
}
/*
* Say the title/message field
*/
VOID IF::SayMessage()
{
rwnd.SayAt(RowEdit(),ColLeft(),szMessage);
}
/*
* Answers with the row for this field..
*/
ROW IF::RowEdit()
{
return (row);
}
/*
* Answers with left edge of this field..
*/
COL IF::ColLeft()
{
return (col);
}
/*
* Answers with the right edge of this field..
*/
COL IF::ColRight()
{
return (col + strlen(szMessage));
}
/*
* Edit field construction.
*/
ED::ED(WINDOW &rwnd,ROW rowStart,COL colStart,SZ szMsg,SZ szDest,CCH cch,SZ szHelpInfo,CENT cent,PENT pent,CENT centDefault) : IF(rwnd,rowStart,colStart,szMsg)
{
Assert(szMsg != szNil);
AssertSz(centDefault < cent,"Default for field not within range");
sz = szDest;
szHelp = szHelpInfo;
dcol = strlen(szMsg) + 2;
szPicture = szNil;
chPicture = 'X';
cchMax = cch;
cchMac = cchNil;
cchCurrent = cchNil;
pfnValid = pfnNil;
pvValid = pvNil;
centValid = cent;
pentValid = pent;
szDefault = pent[centDefault].sz;
SetUnchanged();
SetCursor();
fCareAboutChanges = fTrue;
fNumeric = fFalse;
}
ED::ED(WINDOW &rwnd,ROW rowStart,COL colStart,SZ szMsg,SZ szDest,CHAR ch,CCH cch,SZ szHelpInfo,SZ szDflt) : IF(rwnd,rowStart,colStart,szMsg)
{
Assert(szMsg != szNil);
sz = szDest;
szHelp = szHelpInfo;
dcol = strlen(szMsg) + 2;
szPicture = szNil;
chPicture = ch;
cchMax = cch;
cchMac = cchNil;
cchCurrent = cchNil;
pfnValid = pfnNil;
pvValid = pvNil;
centValid = centNil;
pentValid = pentNil;
szDefault = szDflt;
SetUnchanged();
SetCursor();
fCareAboutChanges = fTrue;
fNumeric = (ch == '9');
}
ED::ED(WINDOW &rwnd,ROW rowStart,COL colStart,SZ szMsg,SZ szDest,SZ szPic,SZ szHelpInfo,SZ szDflt) : IF(rwnd,rowStart,colStart,szMsg)
{
Assert(szPic != szNil);
Assert(szMsg != szNil);
sz = szDest;
szHelp = szHelpInfo;
szPicture = szPic;
dcol = strlen(szMsg) + 2;
cchMax = strlen(szPicture);
cchMac = cchNil;
cchCurrent = cchNil;
pfnValid = pfnNil;
pvValid = pvNil;
centValid = centNil;
pentValid = pentNil;
szDefault = szDflt;
SetUnchanged();
SetCursor();
fCareAboutChanges = fTrue;
fNumeric = fFalse;
}
/*
* Answers if the contents are valid given whatever validation procedure..
*/
BOOL ED::FValidate()
{
BOOL fValid = fTrue;
if (pentValid != pentNil && !FInRange())
fValid = FValidateRange();
else if (pfnValid != pfnNil)
fValid = FValidateFunction();
return (fValid);
}
/*
* Non-standard fields may be modified after being created..
*/
VOID ED::Adjust(PFN pfn,VOID *pv,BOOL fCareIfFieldChanges)
{
pfnValid = pfn;
pvValid = pv;
fCareAboutChanges = fCareIfFieldChanges;
}
/*
* Replaces the current help information..
*/
VOID ED::UpdateHelp(HELP &rhelp)
{
rhelp.Replace(szHelp);
}
/*
* Checks to see if the current input is in the validation array. This
* Array could be in any order, so a linear search is needed..
*/
BOOL ED::FInRange()
{
BOOL fFound = fFalse;
PENT pent = pentValid;
CENT cent = centNil;
/*
* We simply traverse the array, looking for a match. To avoid
* to many strcmp()s, it is only called if the first letter matches..
*/
while (!fFound && cent < centValid)
{
if (*sz == *pent->sz && strcmp(sz,pent->sz) == 0)
{
fFound = fTrue;
}
else
{
cent++;
pent++;
}
}
return (fFound);
}
/*
* Answers if SZ is in the given list of choices..
* In addition, to direct the user to the correct title, that title
* is presented here in white..
*/
BOOL ED::FValidateRange()
{
ROW row = rwnd.RowQuery() + RowEdit() - 2;
COL col = rwnd.ColQuery() + ColLeft() - 1;
POPUP pop(row,col,centValid,pentValid);
CENT cent = pop.CentGet();
BOOL fSelected = fFalse;
if (cent != centError)
{
strcpy(sz,pentValid[cent].sz);
fChanges = fTrue;
SayEdit(fTrue);
fSelected = fTrue;
}
return (fSelected);
}
/*
* Answers if SZ is legal based upon the function call..
*/
BOOL ED::FValidateFunction()
{
return (pfnValid(sz,pvValid));
}
/*
* Answers with the picture character for this position in the edit
*/
CHAR ED::ChPicture()
{
if (szPicture == szNil)
return (chPicture);
else
return (szPicture[cchCurrent]);
}
/*
* Updates display for the current edit. Redraws the entire field. Also,
* asserts the field length is set properly..
*/
VOID ED::SayEdit(BOOL fCurrent)
{
CURSOR crs(fFalse);
/*
* Assert the length is setup properly
*/
cchMac = cchNil;
/*
* Maximum current width is field width..
*/
while (sz[cchMac] != chNil && cchMac < cchMax)
cchMac++;
/*
* Remove/Insert leading WS depending if we are editing a numeric field.
*/
if (fNumeric)
{
Verify(fCurrent ? FStripLeader() : FInsertLeader());
}
/*
* Left Justify output within field, and determine the display colour
*/
SZ szOutput = SzTempPaddedFromSzCch(sz,cchMax);
CO coBack = (fCurrent) ? coGreen : coCyan;
/*
* Output..
*/
rwnd.SayAt(RowEdit(),ColLeft(),szOutput,coBlack,coBack);
}
/*
* Strips leading WS from the edit
*/
BOOL ED::FStripLeader()
{
CCH cch = cchNil;
/*
* Search for the end..
*/
while (cch < cchMac && sz[cch] == chSpace)
cch++;
/*
* Now, copy over..
*/
if (cch != cchNil && cch < cchMac)
{
CCH cchNewMac = cchMac - cch;
memmove(&sz[cchNil],&sz[cch],cchNewMac);
sz[cchNewMac] = chNil;
cchMac = cchNewMac;
}
return (fTrue);
}
/*
* Inserts leading WS into the header
*/
BOOL ED::FInsertLeader()
{
if (cchMac < cchMax)
{
CCH cch = cchMax - cchMac;
memmove(&sz[cch],&sz[cchNil],cchMac);
memset(sz,chSpace,cch);
}
return (fTrue);
}
/*
* Sets the cursor at the far right of the edit.
*/
VOID ED::SetCursor()
{
cchCurrent = cchNil;
/*
* Maximum is field width..
*/
while (sz[cchCurrent] != chNil && cchCurrent < cchMax)
cchCurrent++;
}
/*
* Inserts a character at the current position
*/
BOOL ED::FInsertCd(CD cd)
{
Assert(cchMac <= cchMax);
CHAR ch = (CHAR)cd;
if (FValidChCh(ch,ChPicture()))
{
/*
* Do not write past the end of the region..
*/
if (cchCurrent >= cchMax)
cchCurrent--;
/*
* Make room for this new character.
*/
for (CCH cch = cchMac; cch > cchCurrent; cch--)
{
if (cch < cchMax)
sz[cch] = sz[cch-1];
}
/*
* Now, insert this character..
*/
sz[cchCurrent] = ch;
/*
* Adjust floating length..
*/
if (cchMac < cchMax)
cchMac++;
/*
* Don't forget the \0 at the end if the key
*/
if (cchMac < cchMax)
sz[cchMac] = chNil;
SayEdit(fTrue);
fChanges = fTrue;
CursorRight();
}
return (fTrue);
}
/*
* Cursor manipulation functions
* Right: Must be careful if cchMac == cchMax
*/
VOID ED::CursorRight()
{
cchCurrent++;
/*
* Now, assert it is within range..
*/
if (cchCurrent > cchMac)
cchCurrent--;
}
/*
* Left: Trivial..
*/
VOID ED::CursorLeft()
{
if (cchCurrent > cchNil)
cchCurrent--;
}
/*
* Deletes the current character
*/
BOOL ED::FDelete()
{
if (cchCurrent > 0)
{
cchCurrent -= 1;
fChanges = fTrue;
if (DcolOffset() != 0)
rwnd.SetRowCol(RowEdit(),ColEdit());
rwnd.PutCh(' ',coBlack,coGreen);
}
else if (cchMax == 1)
{
fChanges = fTrue;
rwnd.PutCh(' ',coBlack,coGreen);
}
/*
* No matter where in the edit we were, or what size the field
* is, set that character to chNil
*/
sz[cchCurrent] = chNil;
return (fTrue);
}
/*
* Cursor positioning. DcolOffset computes where to place the cursor.
* Normally, this is one character ahead of the current. If we are
* are at the limit of the field, it is simply there..
*/
COL ED::DcolOffset()
{
return ((cchCurrent == cchMax) ? 0 : 1);
}
/*
* Answers with the left edge of the (edit) field.
*/
COL ED::ColLeft()
{
return (IF::ColLeft()+dcol);
}
/*
* Answers with the current column position for this edit..
*/
COL ED::ColEdit()
{
return (ColLeft()+cchCurrent-1+DcolOffset());
}
/*
* Answers with the far right hand column for this edit..
*/
COL ED::ColRight()
{
return (ColLeft()+cchMax);
}
/*
* Forces the field to be considered unchanged
*/
VOID ED::SetUnchanged()
{
fChanges = fFalse;
}
/*
* Answers if this field has changed. Should consider if we care..
*/
BOOL ED::FModified()
{
return ((fCareAboutChanges) ? fChanges : fFalse);
}
/*
* Input validation routines. This function evalutes the picture and
* the input character. Answers if it is legal given the input..
* If the character is NOT valid, but MAY be mapped onto a valid
* character, that is done and we answer fTrue.
*/
BOOL ED::FValidChCh(CHAR &rch,CHAR chPicture)
{
/*
* PICTURE Templates:
* X- Any printable character
* 9- Digits
* A- Upper case letters, any other char
* a- Lower case letters, any other char
* U- Upper case letters only
* L- Lower case letters only
* N- Upper case Letters, Numbers
* n- Lower case Letters, Numbers
*/
switch (chPicture)
{
case 'X':
return (isprint(rch));
case '9':
return (isdigit(rch));
case 'A':
return (isalpha(rch) ? isupper(rch = toupper(rch)) : isprint(rch));
case 'a':
return (isalpha(rch) ? islower(rch = tolower(rch)) : isprint(rch));
case 'U':
return (isupper(rch = toupper(rch)));
case 'L':
return (islower(rch = tolower(rch)));
case 'N':
return (isalnum(rch));
default:
return (fFalse);
}
}
/*
* Answers if the picture for the current position is "CONSTANT"
*/
BOOL ED::FIsConstantPic()
{
BOOL fConstant = fTrue;
switch (ChPicture())
{
case 'X':
case '9':
case 'A':
case 'a':
case 'U':
case 'L':
case 'N':
fConstant = fFalse;
}
return (fConstant);
}
/*
* Clear() either inserts the default value or clears the field.
*/
VOID ED::Clear()
{
Assert(sz != szNil);
if (szDefault != szNil)
strcpy(sz,szDefault);
else
strcpy(sz,"");
}
/*
* Displays the delimiters for this edit..
*/
VOID ED::ShowDelimiters(CHAR chLeft,CHAR chRight)
{
rwnd.SetRowCol(RowEdit(),ColLeft()-1);
rwnd.PutCh(chLeft);
rwnd.SetRowCol(RowEdit(),ColLeft()+cchMax);
rwnd.PutCh(chRight);
}